package com.atguigu.gmall.mq.listener;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.mq.config.DeadLetterMqConfig;
import com.atguigu.gmall.mq.config.DelayMessageConfig;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;

/**
 * @author 李旭
 * @date 2021/10/25 14:23
 * @Description:
 *
 *   消息接收  消费者
 */
@Component
@Slf4j
public class ConsumerListener {



    //接收基于插件的延迟消息
    @RabbitListener(queues = {DelayMessageConfig.queue_delay_1})
    public void receiverDelayedMessage(String msg,Message message,Channel channel){
        try {
            System.out.println("接收到的延迟消息是：" + msg + ":时间:" + new Date());
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    //接收的基于死信的延迟消息
    @RabbitListener(queues = {DeadLetterMqConfig.queue_dead_2})
    public void receiverDeadLetterMessage(String msg,Message message,Channel channel){
        try {
            System.out.println("接收到的延迟消息是：" + msg + ":时间:" + new Date());
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


















    //接收消息的方法
    //消息对象的组成 ：
    //    1、消息的属性对象（1.1消息头 Map<String, Object> headers  1.2消息的其它属性）
    //private final MessageProperties messageProperties;
    //    2、消息体
    //private final byte[] body;
    @RabbitListener(queues = "queue123")
    //@RabbitHandler
    public void receiverMessage(String msg, Message message, Channel channel){

        //本次监听器是手动应答模型

        //basicAck : 手动应答
        //deliveryTag : 消息的标识符
        //multiple : 是否批量应答消息    预取值  prefetch: 4  表示每次获取4个消息  在信道中
        try {
            System.out.println("直接接收消息：" + msg);
            System.out.println("接收消息对象中的消息体：" + new String(message.getBody()));

            int i = 10/0;//算术异常  RuntimeException  Exception
                         //文件未发现异常 IOException  Exception
            //......

            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            //e.printStackTrace();

            //不应答 操作
            //1:判断是否已经是重新发送的消息
            if(message.getMessageProperties().isRedelivered()){
                 //1.1 是重新发送的   不要再发了  打印日志转人工处理
                log.error("此消息不能再重发消费了:{}", JSONObject.toJSONString(message));

                //拒绝应答  将队列中的消息 删除掉 不要影响到后面的消息的处理
                //deliveryTag : 消息的标识符
                //requeue  : 要求将消息放回队列  消费者重新获取一次消息
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(),
                              false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }else{
                //1.2 是刚来的消息   给一次 重新发送消息的机会
                //deliveryTag : 消息的标识符
                //multiple : 是否批量应答消息    预取值  prefetch: 4  表示每次获取4个消息  在信道中
                //requeue  : 要求将消息放回队列  消费者重新获取一次消息
                log.info("是刚来的消息   给一次 重新发送消息的机会");
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                             false,true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            // 如果同学们想给多点机会 ： 借助外力  Redis进行记录次数

        }
    }






}
